<template>
  <div @mousedown="cancleContext">
    <el-tree
      :ref="`tree_${name}`"
      class="folder-tree"
      :data="state.showTreeData"
      node-key="id"
      :expand-on-click-node="false"
      :default-expanded-keys="state.defaultExpanded"
      @node-contextmenu="rightClick"
      @node-expand="expand"
      @node-collapse="collapse"
    >
      <div
        slot-scope="{ node, data }"
        class="custom-tree-node w-max"
        @dblclick="$emit('dbl-click-node', node)"
        @click="$emit('click-node', data)"
      >
        <svg-icon :icon-class="getIconName(data)" />
        <span v-if="data.isEditName" class="ml-10">
          <el-popover
            v-model="isShowError"
            placement="bottom"
            width="200"
            trigger="manual"
            class="popover"
            :content="`已存在同名${data.isFile ? '文件' : '文件夹'}`"
          >
            <el-input
              slot="reference"
              v-model="editValue"
              v-focus
              size="mini"
              style="width: 100px"
              placeholder="请输入..."
              @keyup.enter.native="data.isEditName = false"
              @focus="inputFocus(node)"
              @input="debouncedInputText(node)"
              @blur="inputBlur(node)"
            />
          </el-popover>
        </span>
        <span v-else class="ml-10">{{ node.label | ellipsis(20) }}</span>
      </div>
    </el-tree>

    <v-contextmenu ref="fileTreeMenu">
      <right-menu :menu-list="menuFileList" :callback="menuClick" />
    </v-contextmenu>
    <v-contextmenu ref="folderTreeMenu">
      <right-menu :menu-list="menuFolderList" :callback="menuClick" />
    </v-contextmenu>
  </div>
</template>

<script>
/**
 * 项目树
 */
import RightMenu from '@/components/menu/RightMenu.vue';
import { debounce } from 'lodash-es';
export default {
  components: {
    RightMenu
  },
  filters: {
    ellipsis(value, len) {
      if (!value) return '';
      if (value.length > len) {
        return value.slice(0, len) + '...';
      }
      return value;
    }
  },
  props: {
    name: {
      type: String,
      default: ''
    },
    menuFolderList: {
      type: Array,
      required: true
    },
    menuFileList: {
      type: Array,
      required: true
    },
    clickFunctions: {
      type: Function,
      required: true
    }
  },
  data() {
    return {
      editValue: '',
      isShowError: false,
      menuData: {}
    };
  },
  computed: {
    state() {
      return this.$store.state[this.name];
    }
  },
  created() {
    this.debouncedInputText = debounce(this.inputText, 200);
  },
  mounted() {
    // 绑定enter事件
    this.keyup();
  },
  destroyed() {
    // 销毁enter事件
    this.keyupDestroyed();
  },
  methods: {
    getIconName(item) {
      const name = item.label;
      const isFile = item.isFile;
      const supportedFileTypes = ['json', 'py', 'txt', 'yaml'];
      const suffix = name.slice(name.lastIndexOf('.') + 1);
      if (isFile) {
        return supportedFileTypes.includes(suffix) ? suffix : 'file';
      } else {
        if (item.projectId || item.tmpProjectIcon) {
          return 'project';
        }
        return 'folderopen';
      }
    },
    expand(data) {
      this.$store.commit(`${this.name}/expand`, data.id);
    },
    collapse(data) {
      this.$store.commit(`${this.name}/collapse`, data.id);
    },
    // 点击右键菜单
    rightClick(event, data, node) {
      this.menuData = { data, node };
      if (node.level === 1) {
        this.$emit('selectedProjectId', data.projectId);
      } else {
        this.$emit('selectedProjectId', data.fatherId);
      }
      const x = parseInt(event.clientX);
      const y = parseInt(event.clientY);
      const postition = {
        top: y,
        left: x
      };
      if (data.isFile) {
        this.$refs.fileTreeMenu.show(postition);
      } else {
        this.$refs.folderTreeMenu.show(postition);
      }
    },
    // 关闭菜单
    cancleContext() {
      this.$refs.folderTreeMenu.hide();
      this.$refs.fileTreeMenu.hide();
    },
    menuClick(type) {
      this.clickFunctions(type, this.menuData);
    },
    expandNode(data) {
      this.$refs[`tree_${this.name}`].store.nodesMap[
        data.id
      ].expanded = true;
    },
    inputFocus(node) {
      if (node.data.label) {
        this.editValue = node.data.label;
      } else {
        this.editValue = node.data.isFile ? 'untitled.py' : node.data.tmpProjectIcon ? 'New Project' : 'New Folder';
      }
    },
    inputText(node) {
      this.isShowError = Boolean(this.checkRepeatName(node));
    },
    // input框失去焦点自动保存（判断名字是否重复）
    inputBlur(node) {
      const data = node.data;
      this.isShowError = false;
      data.isEditName = false;
      const judge = this.checkRepeatName(node);
      if (
        this.editValue.trim() === '' ||
          data.label === this.editValue.trim() ||
          judge
      ) {
        if (judge) {
          this.$message({
            message: `${this.editValue}已存在！请删除后重试！`,
            type: 'warning',
            offset: 40
          });
        }
        if (data.isFirstBuild) {
          // 重名不允许创建
          this.$store.commit(`${this.name}/remove`, { node, data });
        } else {
          this.editValue = '';
        }
        return;
      }
      this.$emit('create-file', node, this.editValue);
      this.editValue = '';
    },
    // 查重名
    checkRepeatName(node) {
      const nodeParent =
          node.parent.data instanceof Array
            ? node.parent.data
            : node.parent.data.children;
      const obj = nodeParent.find((item) => {
        return (
          item.isFile === node.data.isFile &&
            item.label === this.editValue &&
            item.id !== node.data.id
        );
      });
      return obj;
    },
    // 回车键监听
    handleKeyUp(event) {
      const code = event.keyCode
        ? event.keyCode
        : event.which
          ? event.which
          : event.charCode;
      if (code === 13) {
        if (document.activeElement.getAttribute('role') === 'treeitem') {
          const name = `tree_${this.name}`;
          if (this.$refs[name]?.store?.currentNode?.data) {
            const data = this.$refs[name].store.currentNode.data;
            this.$emit('rename', data);
          }
        }
      }
      if (code === 46) {
        if (document.activeElement.getAttribute('role') === 'treeitem') {
          const name = `tree_${this.name}`;
          if (this.$refs[name]?.store?.currentNode?.data) {
            const node = this.$refs[name].store.currentNode;
            const data = this.$refs[name].store.currentNode.data;
            this.$emit('delete', { node, data }, data);
          }
        }
      }
    },
    keyupDestroyed() {
      document.removeEventListener('keyup', this.handleKeyUp);
    },
    keyup() {
      document.addEventListener('keyup', this.handleKeyUp);
    }
  }
};
</script>

<style lang="scss" scoped>
.folder-tree {
  user-select: none;
}
::v-deep .el-tree-node__content {
  height: 30px;
}
.more-icon {
  position: absolute;
  right: 10px;
}
</style>
